package com.wdb007.venus.svc.biz.book;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;

import org.apache.commons.collections.ListUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.wdb007.venus.svc.biz.manager.BookGridManager;
import com.wdb007.venus.svc.biz.manager.ConfigInfoManager;
import com.wdb007.venus.svc.biz.manager.JPushManager;
import com.wdb007.venus.svc.biz.manager.WSBookShelfEnum;
import com.wdb007.venus.svc.biz.manager.WsAPPEnum;
import com.wdb007.venus.svc.biz.utils.DateFormatUtil;
import com.wdb007.venus.svc.biz.utils.DateUtil;
import com.wdb007.venus.svc.biz.utils.MapUtils;
import com.wdb007.venus.svc.dal.book.dao.BookCommentsDAO;
import com.wdb007.venus.svc.dal.book.dao.BookContentAttachDAO;
import com.wdb007.venus.svc.dal.book.dao.BookEntityDAO;
import com.wdb007.venus.svc.dal.book.dao.BookGridDAO;
import com.wdb007.venus.svc.dal.book.dao.BookGridTransDAO;
import com.wdb007.venus.svc.dal.book.dao.BookImageAttachDAO;
import com.wdb007.venus.svc.dal.book.dao.BookImgsDAO;
import com.wdb007.venus.svc.dal.book.dao.BookInfoDAO;
import com.wdb007.venus.svc.dal.book.dao.BookLaunchLogDAO;
import com.wdb007.venus.svc.dal.book.dao.BookRecommendationDAO;
import com.wdb007.venus.svc.dal.book.dao.BookShelfDAO;
import com.wdb007.venus.svc.dal.book.dao.BookTagMappingDAO;
import com.wdb007.venus.svc.dal.book.dao.BookTopicalMappingsDAO;
import com.wdb007.venus.svc.dal.book.model.BRBookTransDO;
import com.wdb007.venus.svc.dal.book.model.BookCommentsAndUserDO;
import com.wdb007.venus.svc.dal.book.model.BookCommentsDO;
import com.wdb007.venus.svc.dal.book.model.BookCommentsPageDO;
import com.wdb007.venus.svc.dal.book.model.BookContentAttachDO;
import com.wdb007.venus.svc.dal.book.model.BookEntityDO;
import com.wdb007.venus.svc.dal.book.model.BookGridDO;
import com.wdb007.venus.svc.dal.book.model.BookGridInfoDO;
import com.wdb007.venus.svc.dal.book.model.BookGridPageDO;
import com.wdb007.venus.svc.dal.book.model.BookGridTransDO;
import com.wdb007.venus.svc.dal.book.model.BookImageAttachDO;
import com.wdb007.venus.svc.dal.book.model.BookInfoDO;
import com.wdb007.venus.svc.dal.book.model.BookLaunchLogDO;
import com.wdb007.venus.svc.dal.book.model.BookQueryPageDO;
import com.wdb007.venus.svc.dal.book.model.BookRecommendationDO;
import com.wdb007.venus.svc.dal.book.model.BookRecommendationInfoDO;
import com.wdb007.venus.svc.dal.book.model.BookShelfAndIsbnDO;
import com.wdb007.venus.svc.dal.book.model.BookShelfDO;
import com.wdb007.venus.svc.dal.book.model.BookTagMappingDO;
import com.wdb007.venus.svc.dal.book.model.BookTopicalMappingsDO;
import com.wdb007.venus.svc.dal.book.model.BorrowedBookDO;
import com.wdb007.venus.svc.dal.book.model.PutonCountQueryDO;
import com.wdb007.venus.svc.dal.dict.dao.DictBookReadableDAO;
import com.wdb007.venus.svc.dal.dict.model.DictBookReadableDO;
import com.wdb007.venus.svc.dal.order.dao.OrderTransDAO;
import com.wdb007.venus.svc.dal.order.model.BorrowingCostDO;
import com.wdb007.venus.svc.dal.order.model.SortedRfidCode;
import com.wdb007.venus.svc.dal.user.dao.UserCostFlagDAO;
import com.wdb007.venus.svc.dal.user.dao.UserInfoDAO;
import com.wdb007.venus.svc.dal.user.dao.UserPointDAO;
import com.wdb007.venus.svc.dal.user.dao.UserPointLogDAO;
import com.wdb007.venus.svc.dal.user.dao.UserWishListDAO;
import com.wdb007.venus.svc.dal.user.model.UserCostFlagDO;
import com.wdb007.venus.svc.dal.user.model.UserInfoDO;
import com.wdb007.venus.svc.dal.user.model.UserPointDO;
import com.wdb007.venus.svc.dal.user.model.UserPointLogDO;
import com.wdb007.venus.svc.dal.user.model.UserWishListDO;
import com.wdb007.venus.svc.dal.user.model.WishInfoQueryDO;
import com.wdb007.venus.svc.facade.BookgridService;
import com.wdb007.venus.svc.facade.BsAlarmService;
import com.wdb007.venus.svc.facade.OrderService;
import com.wdb007.venus.svc.facade.book.model.BRBookDTO;
import com.wdb007.venus.svc.facade.book.model.BRBookResultDTO;
import com.wdb007.venus.svc.facade.book.model.BookCommentsAndUser;
import com.wdb007.venus.svc.facade.book.model.BookCommentsAndUserDTO;
import com.wdb007.venus.svc.facade.book.model.BookCommentsInsertDTO;
import com.wdb007.venus.svc.facade.book.model.BookCommentsQueryPageDTO;
import com.wdb007.venus.svc.facade.book.model.BookGridDTO;
import com.wdb007.venus.svc.facade.book.model.BookGridInfo;
import com.wdb007.venus.svc.facade.book.model.BookGridListDTO;
import com.wdb007.venus.svc.facade.book.model.BookGridListRequestModel;
import com.wdb007.venus.svc.facade.book.model.BookGridPageDTO;
import com.wdb007.venus.svc.facade.book.model.BookGridsDTO;
import com.wdb007.venus.svc.facade.book.model.BookQueryDTO;
import com.wdb007.venus.svc.facade.book.model.BookQueryPageDTO;
import com.wdb007.venus.svc.facade.book.model.BookRecommendationInfoDTO;
import com.wdb007.venus.svc.facade.book.model.BookShelfFavoriteDTO;
import com.wdb007.venus.svc.facade.book.model.BookShelfInfoDTO;
import com.wdb007.venus.svc.facade.book.model.BookTopicalAgeDTO;
import com.wdb007.venus.svc.facade.book.model.BookUrlDTO;
import com.wdb007.venus.svc.facade.book.model.BookgridHardwareDTO;
import com.wdb007.venus.svc.facade.book.model.BookgridUnlockDTO;
import com.wdb007.venus.svc.facade.book.model.BorrowReturnBookDTO;
import com.wdb007.venus.svc.facade.book.model.BorrowedOrReturnBookDTO;
import com.wdb007.venus.svc.facade.book.model.BorrowedOrReturnBookResultDTO;
import com.wdb007.venus.svc.facade.book.model.BorrowedReturnBookResultDTO;
import com.wdb007.venus.svc.facade.book.model.BorrowedUserImgUrlDTO;
import com.wdb007.venus.svc.facade.book.model.PutonBook;
import com.wdb007.venus.svc.facade.book.model.PutonBookPageDTO;
import com.wdb007.venus.svc.facade.book.model.ShareBookDTO;
import com.wdb007.venus.svc.facade.book.model.ShelfBookInfoDTO;
import com.wdb007.venus.svc.facade.book.model.ShelfBookQueryDTO;
import com.wdb007.venus.svc.facade.book.model.SingleGridInventoryDTO;
import com.wdb007.venus.svc.facade.book.model.SingleGridReportDTO;
import com.wdb007.venus.svc.facade.book.model.SingleShelfInventoryDTO;
import com.wdb007.venus.svc.facade.book.model.SingleShelfReportDTO;
import com.wdb007.venus.svc.facade.bs.model.BsAlarmDTO;
import com.wdb007.venus.svc.facade.constant.BizConstants;
import com.wdb007.venus.svc.facade.constant.RspCodeEnum;
import com.wdb007.venus.svc.facade.exception.BizException;
import com.wdb007.venus.svc.facade.model.Age;
import com.wdb007.venus.svc.facade.model.BookTag;
import com.wdb007.venus.svc.facade.model.BookTagAgeDTO;
import com.wdb007.venus.svc.facade.model.BookTopical;
import com.wdb007.venus.svc.facade.model.VenusSvcResp;
import com.wdb007.venus.svc.facade.order.model.OrderInfoDTO;
import com.wdb007.venus.svc.facade.order.model.OrderTransDTO;

@Service("bookgridService")
public class BookgridServiceImpl implements BookgridService {

	private static final Logger logger = LoggerFactory.getLogger(BookgridServiceImpl.class);
	@Autowired
	private OrderTransDAO orderTransDAO;
	
	@Autowired
	private BookGridTransDAO bookGridTransDAO;
	
	@Autowired
	private BookGridDAO bookGridDAO;
	
	@Autowired
	private BookGridManager bookGridManager;
	@Autowired
	private BookEntityDAO bookEntityDAO ;
	@Autowired
	private OrderService orderService;
	@Autowired
	private BookShelfDAO bookShelfDAO ;
	@Autowired
	private DictBookReadableDAO dictBookReadableDAO;
	@Autowired
	private BookTagMappingDAO bookTagMappingDAO;
	
	@Autowired
	private BookTopicalMappingsDAO bookTopicalMappingsDAO;
	
	@Autowired
	private BookInfoDAO bookInfoDAO;
	
	@Autowired
	private BookCommentsDAO bookCommentsDAO;
	
	@Autowired
	private BookRecommendationDAO bookRecommendationDAO;
	
	@Autowired
	private BookImgsDAO bookImgsDAO;
	
	@Autowired
	private BookImageAttachDAO bookImageAttachDAO;
	
	@Autowired
	private UserWishListDAO userWishListDAO;
	
	@Autowired
	private UserCostFlagDAO userCostFlagDAO;
	
	@Autowired
	private UserInfoDAO userInfoDAO;
	
	@Autowired
	private JPushManager jPushManager;
	
	@Autowired
	private BookContentAttachDAO bookContentAttachDAO;
	
	@Autowired
	private UserPointDAO userPointDAO;
	@Autowired
	private UserPointLogDAO userPointLogDAO;
	@Autowired
	private BookLaunchLogDAO bookLaunchLogDAO;
	@Autowired
	private ConfigInfoManager configInfoManager;
	@Autowired
	private BsAlarmService bsAlarmService;
	
	@Override
	public BorrowedReturnBookResultDTO getBrList(BorrowReturnBookDTO brBookDTO) {
		
		BookGridTransDO query = new BookGridTransDO();
		query.setUserId(brBookDTO.getUserId());
		query.setGridCode(brBookDTO.getGridCode());
		query.setLockStatus(BizConstants.GRID_LOCK_STATUS_5);	//5--盘点成功
		query.setPresentDate(new Date());
		query.setUserType(0);
		BookGridTransDO result = bookGridTransDAO.getByCondition(query);
		if(result == null) {
			return null ;
		}
		long gridTransId = result.getId();
		List<BRBookTransDO> list = orderTransDAO.getBrList(gridTransId);
		if(list == null)
			return null ;
		BorrowedReturnBookResultDTO resultDTO = new BorrowedReturnBookResultDTO();
		
		BRBookResultDTO borrowed = new BRBookResultDTO();
		BRBookResultDTO returned = new BRBookResultDTO();
		int borrowCount = 0;
		int returnedCount = 0;
		BigDecimal sum = new BigDecimal(0);	//还书时,总花费金额
		DateFormat df = new SimpleDateFormat("HH:mm");
		for(int i=0; i<list.size(); i++) {
			BRBookTransDO brBookTransDO = list.get(i);
			if(20 == brBookTransDO.getTransStatus()) {
				borrowCount++;
				BRBookDTO brbook = new BRBookDTO();
				brbook.setBookname(brBookTransDO.getBookname());
				brbook.setIsbn(brBookTransDO.getIsbn());
				brbook.setImgurl(configInfoManager.getImgurl(brBookTransDO.getImgurl()));
				borrowed.getList().add(brbook);
				borrowed.setBorrowtime("今天" + df.format(brBookTransDO.getBorrowTime()));
			}else if(30 == brBookTransDO.getTransStatus()) {
				returnedCount++;
				BRBookDTO brbook = new BRBookDTO();
				brbook.setBookname(brBookTransDO.getBookname());
				brbook.setIsbn(brBookTransDO.getIsbn());
				brbook.setImgurl(configInfoManager.getImgurl(brBookTransDO.getImgurl()));
				returned.getList().add(brbook);
				returned.setBorrowtime("今天" + df.format(brBookTransDO.getReturnTime()));
				sum  = sum.add(brBookTransDO.getTransAmount());
			}
			
		}
		String price = configInfoManager.getValue("cost_per_book_per_day");
//		if(borrowCount != 0) {
			borrowed.setBorrowCount(borrowCount);
			borrowed.setCost(new BigDecimal(borrowCount * Double.parseDouble(price)));
			resultDTO.setBorrowed(borrowed);
//		}
//		if(returnedCount != 0) {
			returned.setBorrowCount(returnedCount);
			returned.setCost(sum);
			resultDTO.setReturned(returned);
//		}
		return resultDTO;
	}
	
	private String getCostFlagRemark(Integer costFlag) {
		if(1 == costFlag) {
			return "超额借阅2元/天";
		}else if(2 == costFlag) {
			return "包月期间借阅免费";
		}else if(3 == costFlag) {
			return "包年期间借阅免费";
		}
		return "";
	}
	@Override
	public BorrowedOrReturnBookResultDTO getBrListV2(BorrowReturnBookDTO brBookDTO) throws BizException {
		BookGridTransDO query = new BookGridTransDO();
		query.setUserId(brBookDTO.getUserId());
		query.setGridCode(brBookDTO.getGridCode());
		query.setLockStatus(BizConstants.GRID_LOCK_STATUS_5);	//5--盘点成功
		BookGridTransDO result = bookGridTransDAO.getByCondition(query);
		//获取到最近交易数据
		if(result == null) {
			return null ;
		}
		//超额
		BigDecimal cost_per_book_over_3 =  new BigDecimal(configInfoManager.getValue("cost_per_book_over_3"));
		//还书收费总价
		BigDecimal transAmount = new BigDecimal(0.00);
		
		BorrowedOrReturnBookResultDTO resultDTO = new BorrowedOrReturnBookResultDTO();
		int borrowCount = 0;
		int returnedCount = 0;
		int overBorrowCount = 0;//超额书籍数量
		//根据交易Id获取书籍借还信息
		long gridTransId = result.getId();
		List<BRBookTransDO> list = orderTransDAO.getBrList(gridTransId);
		
		DateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm");

		for(int i=0; i<list.size(); i++) {
			BRBookTransDO brBookTransDO = list.get(i);
			BorrowedOrReturnBookDTO brbook = new BorrowedOrReturnBookDTO();
			if(null == brBookTransDO.getAuthor()) {
				brbook.setAuthor("暂无");
			}else {
				brbook.setAuthor(brBookTransDO.getAuthor());
			}
			if(null == brBookTransDO.getBookname()) {
				brbook.setBookname("暂无");
			}else {
				brbook.setBookname(brBookTransDO.getBookname());
			}
			if(null == brBookTransDO.getImgurl()) {
				brbook.setImgurl(configInfoManager.getBookDefaultImg());
			}else {
				brbook.setImgurl(configInfoManager.getImgurl(brBookTransDO.getImgurl()));
			}
			brbook.setIsbn(brBookTransDO.getIsbn());
			
			brbook.setCost(brBookTransDO.getTransAmount()+"");
			brbook.setCostFlag(brBookTransDO.getCostFlag());
			brbook.setCostFlagRemark(getCostFlagRemark(brBookTransDO.getCostFlag()));
			//借书
			brbook.setStarttime(df.format(brBookTransDO.getBorrowTime()));
			if(20 == brBookTransDO.getTransStatus()) {
				
//				if(brBookTransDO.getBorrowPrice().compareTo(cost_per_book_over_3) == 0) {
//					brbook.setType((byte)11);//借书 超额
//				}else {
//					brbook.setType((byte) 1);//借书
//				}
				brbook.setType((byte)1);//借书
				borrowCount++;
				//超额书籍数量
				if(brBookTransDO.getCostFlag() == 1) {
					overBorrowCount++;
				}
			}else if(30 == brBookTransDO.getTransStatus()) {
				returnedCount++;
//				if(brBookTransDO.getBorrowPrice().compareTo(cost_per_book_over_3) == 0) {
//					brbook.setType((byte)21);//还书 超额
//				}else {
//					brbook.setType((byte) 2);//还书
//				}
				brbook.setType((byte) 2);//还书
				brbook.setReturntime(df.format(brBookTransDO.getReturnTime()));
				brbook.setBorrowtime(DateUtil.getDatePoor(brBookTransDO.getReturnTime(), brBookTransDO.getBorrowTime()));
				transAmount = brBookTransDO.getTransAmount().add(transAmount);
				
			}
			resultDTO.getList().add(brbook);
		}
		
		resultDTO.setBorrowCount(borrowCount);
		resultDTO.setReturnCount(returnedCount);
		resultDTO.setTransAmount(transAmount);
				
		return resultDTO;
	}

	@Override
	public BookgridUnlockDTO unlock(BookgridUnlockDTO request)  throws BizException{
		
		BookgridUnlockDTO result = new BookgridUnlockDTO();
		
		String gridCode = request.getGridCode();
		Long userid = request.getUserid();
		result.setStatus("0"); //默认为 status=0,表示书格正常
		//1.1 判断书格状态是否正常
		BookGridDO query = bookGridDAO.get(gridCode);
		UserInfoDO userInfo = userInfoDAO.get(userid);
		Integer userType = userInfo.getUserType();
		if(query == null) {
			result.setStatus("1");	//status=1 表示 该书格不存在
			return result ;
		}
		if(0 == query.getAvailable()) {
			result.setStatus("4");	//status=0 表示 该书格不可用
			return result ;
		}
		if(2 == query.getDamageReport()) {
			result.setStatus("2");	//status=2 表示 该书格已报修，不能使用
			return result ;
		}
		if(query.getLockStatus() == BizConstants.GRID_LOCK_STATUS_1) {	
			//lock_status =2 打开失败; lock_status = 5 盘点结束
			result.setStatus("3");	//status=3 表示 该书格目前处于非关闭状态，不能使用
			return result ;
		}
		
		//1.2.记录书格开门时间
		BookGridTransDO bookGridTransDO = new BookGridTransDO();
		bookGridTransDO.setGridCode(gridCode);
		bookGridTransDO.setUserId(userid);
		bookGridTransDO.setUserType(userType);
		bookGridTransDO.setCreateTime(DateUtil.now());
		bookGridTransDO.setModifyTime(DateUtil.now());
		bookGridTransDO.setPresentDate(new Date());
		bookGridTransDO.setLockStatus(BizConstants.GRID_LOCK_STATUS_0);
		bookGridTransDAO.insert(bookGridTransDO);
		//1.3.
		BookGridDO bookGridDO = new BookGridDO();
		bookGridDO.setBookgridCode(gridCode);
		bookGridDO.setLockStatus(BizConstants.GRID_LOCK_STATUS_0);
		bookGridDO.setModifyTime(DateUtil.now());
		bookGridDAO.update(bookGridDO);
		//2.调用书格开门API
		bookGridManager.notifyBookGrid(gridCode, bookGridTransDO.getId(), WSBookShelfEnum.bookgrid_unlock_req);
		result.setGridCode(gridCode);
		return result;
	}

	/**
	 * 书柜通知后端，书格已经打开  方法处理
	 */
	@Override
	public void notifyUnlock(BookgridHardwareDTO bookgridHardwareDTO)  throws BizException{
		
		//2.修改书格变化表中的状态，以及书格表中的状态
		String grid_code = bookgridHardwareDTO.getBookgrid_code() ;
		BookGridTransDO bookGridTransDO = bookGridTransDAO.get(Long.valueOf(bookgridHardwareDTO.getGridtrans_id()));
		if(bookGridTransDO == null) {
			return ;
		}
		logger.info("书格[{}]数据库中的状态为 [{}]", grid_code, bookGridTransDO.getLockStatus());
		Integer userType = bookGridTransDO.getUserType();
		if(BizConstants.GRID_LOCK_STATUS_1 == bookGridTransDO.getLockStatus()) {		//如果已经开门，则不进行后续操作
			return ;
		}
		if(BizConstants.GRID_LOCK_STATUS_0 == bookgridHardwareDTO.getStatus()) {		//0 表示开门失败
			bookGridTransDO.setLockStatus(BizConstants.GRID_LOCK_STATUS_2);
		}else {
			bookGridTransDO.setLockStatus(BizConstants.GRID_LOCK_STATUS_1);			//1表示开门成功
			bookGridTransDO.setCreateTime(DateUtil.now());
			bookGridTransDO.setModifyTime(DateUtil.now());
		}
		bookGridTransDAO.update(bookGridTransDO);
		
		BookGridDO bookGridDO = bookGridDAO.get(grid_code);
		String action = "";
		if(0 == bookgridHardwareDTO.getStatus()) {		//0 表示开门失败
			bookGridDO.setLockStatus(BizConstants.GRID_LOCK_STATUS_2);
			action = WsAPPEnum.unlock_failed.name();
		}else {					
			bookGridDO.setLockStatus(BizConstants.GRID_LOCK_STATUS_1);				//1表示开门成功
			action =  WsAPPEnum.unlock_success.name();
		}	
		bookGridDAO.update(bookGridDO);
		
		//2.通知数据总线该书柜已打开 或失败
//		if(BizConstants.GRID_TRANS_USER_TYPE_0 == userType)
//			bookGridManager.notifyApp(bookGridTransDO.getUserId(), grid_code, action);
//		else
//			bookGridManager.notifyWx(bookGridTransDO.getUserId(), grid_code, action);
	}
	
	@Override
	public void unlockAll(Map<String, String> map) throws BizException{
		Set<Entry<String, String>> es = map.entrySet();
		for(Entry<String, String> entry : es) {
			String bookGridCode = entry.getKey();
			String status  = entry.getValue();
			
			logger.info("unlockAll书格[{}]当前状态为: [{}]", bookGridCode, status);
			
		}
		
	}
	
	/**
	 * 书柜通知后端，关门成功.只是更新数据
	 * @param bookgridHardwareDTO
	 */
	@Override
	public VenusSvcResp notifyLock(BookgridHardwareDTO bookgridHardwareDTO)  throws BizException{
		VenusSvcResp resp = new VenusSvcResp();
		String grid_code = bookgridHardwareDTO.getBookgrid_code();
		
		//2.开始计费
		//2.1 判断用户开锁时间，是否超过15分钟，是否需要计费
		BookGridTransDO query = new BookGridTransDO();
		query.setGridCode(grid_code);
		query.setLockStatus(BizConstants.GRID_LOCK_STATUS_1);
		BookGridTransDO bookGridTransDO = bookGridTransDAO.getByCondition(query);
		if(null == bookGridTransDO) {
			resp = new  VenusSvcResp(RspCodeEnum.BOOK_GRID_STATUS_IS_NON_OPENED);
			return resp;
		}
		Long bookGridTransId = bookGridTransDO.getId();
		Long userid = bookGridTransDO.getUserId();
		Integer userType = bookGridTransDO.getUserType();
		bookGridTransDO.setLockStatus(BizConstants.GRID_LOCK_STATUS_3);
		bookGridTransDO.setModifyTime(new Date());
		bookGridTransDAO.update(bookGridTransDO);
		//调用扣款接口，对超过10分钟的书格进行扣款
//		if(BizConstants.GRID_TRANS_USER_TYPE_0 == userType)
//			orderService.gridCharge(userid, grid_code, bookGridTransId);
		//同时需要更新书格中的状态
		BookGridDO bookGridDO = bookGridDAO.get(grid_code);
		bookGridDO.setLockStatus(BizConstants.GRID_LOCK_STATUS_3);
		bookGridDO.setModifyTime(new Date());
		bookGridDAO.update(bookGridDO);
		//通知APP，关门完成
//		if(BizConstants.GRID_TRANS_USER_TYPE_0 == userType)
//			bookGridManager.notifyApp(userid, grid_code, WsAPPEnum.lock_success.name());
//		else
//			bookGridManager.notifyWx(userid, grid_code, WsAPPEnum.lock_success.name());
		return resp;
	}
	/**
	 * 查询书格状态
	 * @param gridCode
	 * @return
	 */
	public Integer queryStatus(String gridCode)  throws BizException{
		BookGridDO bookGridDO = bookGridDAO.get(gridCode);
		
		if(BizConstants.GRID_LOCK_STATUS_3.equals(bookGridDO.getLockStatus())) {
			Date lastTime = bookGridDO.getModifyTime();
			if((System.currentTimeMillis() - lastTime.getTime()) > 10000) {	//目前加判断，只有在关门大于8秒后，才会给书柜请求单书格盘点。
				//通过书柜进行书格盘点
				logger.info("超过8秒，主动发送单书格盘点[{}]请求....", gridCode);
				bookGridDO.setModifyTime(new Date());
				bookGridDAO.update(bookGridDO);
				bookGridManager.notifyBookGrid(gridCode, null, WSBookShelfEnum.bookgrid_check_req);
			}
		}
		return bookGridDO.getLockStatus();
	}
	
	/**
	 * 查询该用户，该书格剩余可用时间
	 * @param gridCode
	 * @param userid
	 * @return 秒数
	 */
	public Integer queryRemainingSeconds(String gridCode, Long userid)  throws BizException{
		BookGridTransDO query = new BookGridTransDO();
		query.setPresentDate(new Date());
		query.setUserId(userid);
		query.setUserType(BizConstants.GRID_TRANS_USER_TYPE_0);
		query.setGridCode(gridCode);
		Integer costed = bookGridTransDAO.getRemainingSeconds(query);
		if(null == costed)
			costed = 0;
		if(costed >= BizConstants.BILLING_BASE) {
			return 0;
		}
		return BizConstants.BILLING_BASE - costed;
	}
	
	@Override
	public String bookGridCheck(String bookgrid_code, List<String> rfidCodes) throws BizException {
		
		logger.info("singleGridInventory's 从书柜中盘点的rfidCodes: {}" ,rfidCodes);
		//数据库中查询的rfidcode 信息
		List<String> db_rfidcodes = bookEntityDAO.getRfidcodes(bookgrid_code);
		logger.info("singleGridInventory's 从数据库中获取的origRfidCodes: {}" ,db_rfidcodes);
		//1 得到本次借出的图书的rfid
		List<String> borrowedRfidCodes = ListUtils.subtract(db_rfidcodes, rfidCodes);
		logger.info("singleGridInventory's 计算得到的的borrowedRfidCodes: {}" ,borrowedRfidCodes);
		//2得到本次归还的图书的rfid
		List<String> returnedRfidCodes = ListUtils.subtract(rfidCodes, db_rfidcodes);
		logger.info("singleGridInventory's 计算得到的的returnedRfidCodes: {}" ,returnedRfidCodes);
		
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("bookgrid_code", bookgrid_code);
		jsonObject.put("data", rfidCodes);
		//盘点数据与数据库数据落地
		singleGridLand(jsonObject, bookgrid_code, db_rfidcodes);
		//数据入库
		String userid = bookGridIntoDB(bookgrid_code, borrowedRfidCodes, returnedRfidCodes);
		return userid;
	}
	
	
	
	
	/**
	 * 盘点数据入库
	 * @param bookgrid_code 书格编号
	 * @param borrowedRfidCodes 统计出来的借出的图书RFID
	 * @param returnedRfidCodes 统计出来的归还的图书RFID
	 * @throws BizException 
	 */
	private String bookGridIntoDB(String bookgrid_code, List<String> borrowedRfidCodes,
			List<String> returnedRfidCodes) throws BizException {
		//1.查询书格状态
		BookGridDO bookGrid = bookGridDAO.get(bookgrid_code);
		logger.info("书格[{}]此时lock_status = {}", bookgrid_code, bookGrid.getLockStatus());
		BookGridTransDO bookGridTrans = null;
		Integer flag = 0;	//flag字段用来判断是关门之后盘点，还是请求盘点之后的盘点
		if(BizConstants.GRID_LOCK_STATUS_3 == bookGrid.getLockStatus() || BizConstants.GRID_LOCK_STATUS_4 == bookGrid.getLockStatus()) {
			BookGridTransDO bgtQuery = new BookGridTransDO();
			bgtQuery.setGridCode(bookgrid_code);
			bgtQuery.setLockStatus(bookGrid.getLockStatus());
			bookGridTrans = bookGridTransDAO.getByCondition(bgtQuery);
			if(null == bookGridTrans) {
				logger.warn("warn =====书格[{}]开柜流水信息不存在，直接返回" , bookgrid_code);
				return null;
			}
			if(BizConstants.GRID_LOCK_STATUS_3 == bookGrid.getLockStatus())
				flag = 0;
			else
				flag = 1;
		}else {
			bookGridTrans = new BookGridTransDO();
			bookGridTrans.setCreateTime(new Date());
			bookGridTrans.setGridCode(bookgrid_code);
			bookGridTrans.setLockStatus(BizConstants.GRID_LOCK_STATUS_5);
			bookGridTrans.setPresentDate(new Date());
			bookGridTrans.setUserId(Long.valueOf(configInfoManager.getValue("default_maintain_user_id")));
			bookGridTrans.setUserType(1);
			bookGridTransDAO.insert(bookGridTrans);
		}
		
		Long gridTransId = bookGridTrans.getId();
		Long userId = bookGridTrans.getUserId();
		Integer userType = bookGridTrans.getUserType();
		
		//还书、放书
		if(!CollectionUtils.isEmpty(returnedRfidCodes)) {
			Set<Long> orderIdSet = new HashSet<Long>();	//订单集合
			SortedRfidCode sortedRfidCode = new SortedRfidCode();
			sortedRfidCode.setList(returnedRfidCodes);
			List<String> sortedRfidCodes = orderTransDAO.getSortedRfidCodeList(sortedRfidCode );
			if(null == sortedRfidCodes || sortedRfidCodes.size() == 0 || sortedRfidCodes.size() != returnedRfidCodes.size()) {
				sortedRfidCodes = returnedRfidCodes;
			}
			for(String rfidCode : sortedRfidCodes) {
				//1.更新书格、图书 关联表中的关系
				BookEntityDO bookEntityDO = bookEntityDAO.get(rfidCode);
				if(null == bookEntityDO) {
					logger.error("return=====bookgridCheck========书格编号[{}]中， rfid:{} NotFoundInBookEntity",bookgrid_code, rfidCode);
					continue;
				}
				Integer borrowedStatus = bookEntityDO.getBorrowedStatus();
				if(null == bookEntityDO.getCurrentGridCode()) {	//FIXME 此处需要区分普通用户或者运维用户嘛?理论上只有运维人员，才存在这种情况
					logger.warn("warn===bookgridCheck 书格编号[{}]中， rfid:{} 进行初始化信息，不参与计费", bookgrid_code, rfidCode);
					bookEntityDO.setBorrowedStatus(BizConstants.BOOK_BORROW_STATUS_0);
					bookEntityDO.setCreateTime(new Date());
					bookEntityDO.setCurrentGridCode(bookgrid_code);
					bookEntityDO.setOriginGridCode(bookgrid_code);
					bookEntityDO.setPutonDate(new Date());
					bookEntityDO.setStatus(1);
					bookEntityDAO.update(bookEntityDO);
					
					//插入图书投放流水表
					BookLaunchLogDO bookLaunchLog = new BookLaunchLogDO();
					bookLaunchLog.setGridCode(bookgrid_code);
					bookLaunchLog.setRfidCode(rfidCode);
					bookLaunchLog.setIsbnNo(bookEntityDO.getIsbnNo());
					bookLaunchLog.setOpFlag(0);
					bookLaunchLog.setId(UUID.randomUUID().toString().replaceAll("-", ""));
					bookLaunchLog.setUserId(userId);
					bookLaunchLog.setOpTime(new Date());
					bookLaunchLogDAO.insert(bookLaunchLog);
					continue;
				}
				if(borrowedStatus == BizConstants.BOOK_BORROW_STATUS_1) {
					BookLaunchLogDO bookLaunchLog = new BookLaunchLogDO();
					bookLaunchLog.setGridCode(bookgrid_code);
					bookLaunchLog.setRfidCode(rfidCode);
					bookLaunchLog.setIsbnNo(bookEntityDO.getIsbnNo());
					bookLaunchLog.setOpFlag(0);
					bookLaunchLog.setId(UUID.randomUUID().toString().replaceAll("-", ""));
					bookLaunchLog.setUserId(userId);
					bookLaunchLog.setOpTime(new Date());
					bookLaunchLogDAO.insert(bookLaunchLog);
				}
				bookEntityDO.setModifyTime(new Date());
				bookEntityDO.setBorrowedStatus(BizConstants.BOOK_BORROW_STATUS_0);
				bookEntityDO.setCurrentGridCode(bookgrid_code);
				bookEntityDAO.update(bookEntityDO);
				
				//2.更新用户借还流水表数据
				OrderTransDTO orderTransDTO = new OrderTransDTO();
				orderTransDTO.setGridTransId(gridTransId);
				orderTransDTO.setRfidCode(rfidCode);
				orderTransDTO.setRestituteGridCode(bookgrid_code);
				orderTransDTO.setRestituteShelfCode(bookgrid_code.substring(0, 10));
				orderService.finishOrderTrans(orderTransDTO, flag, userId);
				if(null != orderTransDTO.getOrderId()) {
					orderIdSet.add(orderTransDTO.getOrderId());
				}
			}
			//更新订单信息
			orderService.finishOrders(orderIdSet);
		}
		
		//针对借阅的图书，开始生成订单
		if(!CollectionUtils.isEmpty(borrowedRfidCodes)) {
			//2.3.1创建订单
			OrderInfoDTO orderInfo = new OrderInfoDTO();
			orderInfo.setCreateTime(new Date());
			orderInfo.setOrderType(BizConstants.ORDER_TYPE_10);
			orderInfo.setStatus(BizConstants.ORDER_STATUS_20);
			orderInfo.setUserId(userId);
			orderService.setupOrder(orderInfo);
			long orderId = orderInfo.getId();
			//根据grid_code 得到shelf_code
			String shelfCode = bookGridDAO.getBookShelfCode(bookgrid_code);
			
			//借阅数量
			int borrowCount = 0;
			//超额书籍数量
			int overBorrowCount = 0;
			//超额书籍isbn
			String overBorrowName = "";
			
			for(String rfidCode : borrowedRfidCodes) {
				//更新书格、图书 关联表中的关系
				BookEntityDO bookEntityDO = bookEntityDAO.get(rfidCode);
				if(null == bookEntityDO) {
					logger.error("borrow=====bookgridCheck========书格编号[{}]中， rfid:{} NotFoundInBookEntity",bookgrid_code, rfidCode);
					continue;
				}
				bookEntityDO.setModifyTime(DateUtil.now());
				if(0 == userType) {	//如果是正常用户，则是借阅
					bookEntityDO.setBorrowedStatus(BizConstants.BOOK_BORROW_STATUS_2);
				}else {				//如果是运维人员，则是下架
					bookEntityDO.setBorrowedStatus(BizConstants.BOOK_BORROW_STATUS_1);
					
					//插入图书投放流水表
					BookLaunchLogDO bookLaunchLog = new BookLaunchLogDO();
					bookLaunchLog.setGridCode(bookgrid_code);
					bookLaunchLog.setRfidCode(rfidCode);
					bookLaunchLog.setIsbnNo(bookEntityDO.getIsbnNo());
					bookLaunchLog.setOpFlag(1);
					bookLaunchLog.setId(UUID.randomUUID().toString().replaceAll("-", ""));
					bookLaunchLog.setUserId(userId);
					bookLaunchLog.setOpTime(new Date());
					bookLaunchLogDAO.insert(bookLaunchLog);
				}
				bookEntityDAO.update(bookEntityDO);
				
				borrowCount++;
				//创建 用户借还流水表
				OrderTransDTO orderTransDTO = new OrderTransDTO();
				orderTransDTO.setOrderId(orderId);
				orderTransDTO.setGridTransId(gridTransId);
				orderTransDTO.setRfidCode(rfidCode);
				orderTransDTO.setGridCode(bookgrid_code);
				orderTransDTO.setShelfCode(shelfCode);
				orderTransDTO.setTransStatus(BizConstants.ORDER_TRANS_STATUS_20);
				orderTransDTO.setBorrowDate(DateUtil.now());
				orderTransDTO.setCreateTime(DateUtil.now());
				orderTransDTO.setUserId(userId);
				orderTransDTO.setChargeCount(0);
				if(1 == userType) {	//如果是运维人员，计费为0
					orderTransDTO.setBorrowPrice(new BigDecimal("0.00"));
					orderTransDTO.setCostFlag(2);
				}else {				//如果是正常用户，则正常计费
					orderTransDTO.setBorrowPrice(getCostPerday(userId));
					orderTransDTO.setCostFlag(getCostFlag(userId));
					BigDecimal cost_per_book_over_3 =  new BigDecimal(configInfoManager.getValue("cost_per_book_over_3"));
					if(cost_per_book_over_3.compareTo(orderTransDTO.getBorrowPrice()) == 0) {
						orderTransDTO.setCostFlag(1);
						//rfid查到isbn 查到bookname
						overBorrowName += "《"+bookInfoDAO.get(bookEntityDAO.get(orderTransDTO.getRfidCode()).getIsbnNo()).getBookName() + "》 ";
						overBorrowCount++;
					}
				}
				orderService.setupOrderTrans(orderTransDTO);
				//更新用户心愿单数据
				UserWishListDO userWishListQuery = new UserWishListDO();	
				userWishListQuery.setUserId(userId);
				userWishListQuery.setIsbn(bookEntityDO.getIsbnNo());
				userWishListQuery.setStatus(0);
				UserWishListDO userWishListResult = userWishListDAO.getByCondition(userWishListQuery);
				if(userWishListResult != null) {
					userWishListResult.setModifyTime(new Date());
					userWishListResult.setStatus(1);
					userWishListDAO.update(userWishListResult);
				}
			}
			//超额借阅通知暂不开放
//			if(overBorrowCount > 0) {
//				wxAPPMessagePushService.sendBorrowBookOverNotice(borrowCount, overBorrowCount, overBorrowName, orderInfo.getCreateTime() , userId);
//			}
		}
		//-----------------书格数量以及书柜数量报警start------------------------
				int bookCaseCount = bookEntityDAO.getBookCaseTotalCount(bookgrid_code.substring(0,10));
				int bookGridCount = bookEntityDAO.getBookGridTotalCount(bookgrid_code);
				
				int bookgrid_high_threshold = Integer.valueOf(configInfoManager.getValue("bookgrid_high_threshold"));
				int bookcase_high_threshold = Integer.valueOf(configInfoManager.getValue("bookcase_high_threshold"));
				int bookcase_low_threshold = Integer.valueOf(configInfoManager.getValue("bookcase_low_threshold"));
				int bookgrid_low_threshold = Integer.valueOf(configInfoManager.getValue("bookgrid_low_threshold"));
				
			//	int normalCaseCount = grid_book_count * bookGridDAO.getBookGridCodes(bookgrid_code.substring(0,10)).size();
				if(bookCaseCount > bookcase_high_threshold) {	//超过指定的书柜数量
					BsAlarmDTO bsAlarm = new BsAlarmDTO();
					bsAlarm.setAlarmContent("书柜["+bookgrid_code.substring(0,10)+"]当前数量["+bookCaseCount+"],超过限定值["+bookcase_high_threshold+"],异常");
					bsAlarm.setBookgridCode(bookgrid_code.substring(0,10)+"00");
					bsAlarm.setAlarmType(BizConstants.BS_ALARM_TYPE_5);
					bsAlarmService.saveBsAlarm(bsAlarm);
				}
				if(bookCaseCount < bookcase_low_threshold) {	//超过指定的书柜数量
					BsAlarmDTO bsAlarm = new BsAlarmDTO();
					bsAlarm.setAlarmContent("书柜["+bookgrid_code.substring(0,10)+"]当前数量["+bookCaseCount+"],低于限定值["+bookcase_low_threshold+"],异常");
					bsAlarm.setBookgridCode(bookgrid_code.substring(0,10)+"00");
					bsAlarm.setAlarmType(BizConstants.BS_ALARM_TYPE_5);
					bsAlarmService.saveBsAlarm(bsAlarm);
				}
				if(bookGridCount < bookgrid_low_threshold) {
					BsAlarmDTO bsAlarm = new BsAlarmDTO();
					bsAlarm.setAlarmContent("书格["+bookgrid_code+"]当前数量["+bookGridCount+"],低于限定值["+bookgrid_low_threshold+"],异常");
					bsAlarm.setBookgridCode(bookgrid_code);
					bsAlarm.setAlarmType(BizConstants.BS_ALARM_TYPE_6);
					bsAlarmService.saveBsAlarm(bsAlarm);
				}
				if(bookGridCount > bookgrid_high_threshold) {
					BsAlarmDTO bsAlarm = new BsAlarmDTO();
					bsAlarm.setAlarmContent("书格["+bookgrid_code+"]当前数量["+bookGridCount+"],高于限定值["+bookgrid_high_threshold+"],异常");
					bsAlarm.setBookgridCode(bookgrid_code);
					bsAlarm.setAlarmType(BizConstants.BS_ALARM_TYPE_6);
					bsAlarmService.saveBsAlarm(bsAlarm);
				}
				//-----------------书格数量以及书柜数量报警end------------------------
				
				
				//-----------------用户一次性借书数量报警start------------------------
				Integer costFlag = getCostFlag(userId);
				int borrowCount = CollectionUtils.isEmpty(borrowedRfidCodes) ? 0 : borrowedRfidCodes.size();
				String mobile = userInfoDAO.get(userId).getMobileNo();
				if(2 == costFlag && borrowCount > 3 && 0 == userType) { //月卡超额报警
					BsAlarmDTO bsAlarm = new BsAlarmDTO();
					bsAlarm.setAlarmContent("用户["+mobile+"]月卡会员，借阅超过3本，异常");
					bsAlarm.setBookgridCode(bookgrid_code);
					bsAlarm.setAlarmType(BizConstants.BS_ALARM_TYPE_7);
					bsAlarmService.saveBsAlarm(bsAlarm);
				}else if(3 == costFlag && borrowCount > 5 && 0 == userType) { //年卡超额报警
					BsAlarmDTO bsAlarm = new BsAlarmDTO();
					bsAlarm.setAlarmContent("用户["+mobile+"]年卡会员，借阅超过5本，异常");
					bsAlarm.setBookgridCode(bookgrid_code);
					bsAlarm.setAlarmType(BizConstants.BS_ALARM_TYPE_7);
					bsAlarmService.saveBsAlarm(bsAlarm);
				}else if(0 == costFlag && borrowCount > 3 && 0 == userType) { //正常借阅报警
					BsAlarmDTO bsAlarm = new BsAlarmDTO();
					bsAlarm.setAlarmContent("用户["+mobile+"]非会员，借阅超过3本，异常");
					bsAlarm.setBookgridCode(bookgrid_code);
					bsAlarm.setAlarmType(BizConstants.BS_ALARM_TYPE_7);
					bsAlarmService.saveBsAlarm(bsAlarm);
				}
				//-----------------用户一次性借书数量报警end------------------------
		//更新书格状态，并通知APP
		if(BizConstants.GRID_LOCK_STATUS_3 == bookGrid.getLockStatus() || BizConstants.GRID_LOCK_STATUS_4 == bookGrid.getLockStatus()) {
			bookGrid.setLockStatus(BizConstants.GRID_LOCK_STATUS_5);
			bookGrid.setModifyTime(new Date());
			bookGridDAO.update(bookGrid);
			bookGridTrans.setLockStatus(BizConstants.GRID_LOCK_STATUS_5);
			bookGridTrans.setModifyTime(new Date());
			bookGridTransDAO.update(bookGridTrans);
			return bookGridTrans.getUserId()+"";
//			bookGridManager.notifyApp(userId, bookgrid_code, WsAPPEnum.stocktaking_success.name());
		}

		return null;
	}

	private Integer getCostFlag(Long userId) {
		UserCostFlagDO userCostFlag = userCostFlagDAO.getByUserId(userId);
		if(null == userCostFlag) {
			return 0;
		}
		if(3 == userCostFlag.getCostOrder()) {
			return 2;
		}
		if(4 == userCostFlag.getCostOrder()) {
			return 3;
		}
		return 0;
	}
	private BigDecimal getCostPerday(Long userId){
		BigDecimal cost_per_book_per_day =  new BigDecimal(configInfoManager.getValue("cost_per_book_per_day"));
		int borrowCountNormal = Integer.valueOf(configInfoManager.getValue("borrow_count_normal"));
		BigDecimal cost_per_book_over_3 =  new BigDecimal(configInfoManager.getValue("cost_per_book_over_3"));
		UserCostFlagDO userCostFlag = userCostFlagDAO.getByUserId(userId);

		if(userCostFlag != null) {
			Integer costOrder = userCostFlag.getCostOrder();
			if(3 == costOrder) {
				Date endTime = DateFormatUtil.getMaxTimeDay(userCostFlag.getEndTime());
				if(endTime.compareTo(new Date()) >= 0) {
					borrowCountNormal = 3;
					cost_per_book_per_day = userCostFlag.getPrice();
				}else {
					//FIXME 更新该条VIP信息为过期VIP信息
					userCostFlag.setValidFlag(0);
					userCostFlag.setModifyTime(new Date());
					userCostFlagDAO.update(userCostFlag);
					cost_per_book_per_day = getCostPerday(userId);
				}
			}else if(4 == costOrder) {
				Date endTime = DateFormatUtil.getMaxTimeDay(userCostFlag.getEndTime());
				if(endTime.compareTo(new Date()) >= 0) {
					borrowCountNormal = 5;
					cost_per_book_per_day = userCostFlag.getPrice();
				}else {
					//FIXME 更新该条VIP信息为过期VIP信息
					userCostFlag.setValidFlag(0);
					userCostFlag.setModifyTime(new Date());
					userCostFlagDAO.update(userCostFlag);
					cost_per_book_per_day = getCostPerday(userId);
				}
			}else {
				cost_per_book_per_day = userCostFlag.getPrice();
			}
		}
		Integer count = orderTransDAO.getBorrowingCount(userId);
		if((count+1) > borrowCountNormal) {
			return cost_per_book_over_3;
		}else {
			return cost_per_book_per_day;
		}
	}
	@SuppressWarnings("unchecked")
	@Override
	public void singleGridInventory(SingleGridInventoryDTO singleGridInventory)  throws BizException{
		
		JSONObject jsonObject = (JSONObject) JSON.parse(singleGridInventory.getStockdata());
		String bookgrid_code = (String) jsonObject.get("bookgrid_code");
		
		//书格传递过来的rfidcode 信息
		List<String> rfidCodes = (List)JSON.parse(jsonObject.get("data")+"");
		
		bookGridCheck(bookgrid_code, rfidCodes);
	}
	/**
	 * 单个书格盘点图书信息落地
	 * @param jsonObject
	 * @param bookgrid_code
	 * @param db_rfidcodes
	 */
	private void singleGridLand(JSONObject jsonObject, String bookgrid_code, List<String> db_rfidcodes) {
		//2.创建目录
		String os = System.getenv("OS");
		String single_grid_inventory_path = "";
		if("Windows_NT".equalsIgnoreCase(os)) {
			single_grid_inventory_path = configInfoManager.getValue("single_grid_inventory_path_windows");
		}else {
			single_grid_inventory_path = configInfoManager.getValue("single_grid_inventory_path");
		}
		DateFormat df = new SimpleDateFormat("yyyyMMdd");
		String datePath = df.format(new Date());
		String yearMonth = datePath.substring(0, 6);
		String day = datePath.substring(6);
		File dir = mkdir(single_grid_inventory_path, yearMonth);
		File gridcode_file = new File(dir, day+"_"+bookgrid_code + ".txt");
		if(!gridcode_file.exists()) {
			try {
				gridcode_file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		String grid_data_json = jsonObject.toJSONString();
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("bookgrid_code", bookgrid_code);
		map.put("data", db_rfidcodes);
		String db_data_json = JSON.toJSONString(map);
		//3.写入数据
		String[] lines = new String[] {DateFormatUtil.formatDateTime(new Date()),grid_data_json, db_data_json, System.getProperty("line.separator")};
		try {
			IOUtils.writeLines(Arrays.asList(lines), null, new FileOutputStream(gridcode_file), Charset.forName("UTF-8"));
		} catch (IOException e) {
			logger.error("写入文件[" + gridcode_file.getAbsolutePath() + "]异常", e);
		}
	}
	
	private File mkdir(String path, String child) {
		File parentFile = new File(path);
		if(!parentFile.exists() || !parentFile.isDirectory()) {
			parentFile.mkdirs();
		}
		File file = new File(parentFile, child);
		if(!file.exists() || !file.isDirectory()) {
			file.mkdirs();
		}
		return file;
	}

	private List<String> toUpperList(List<String> lowerList) {
		List<String> upperList = new ArrayList<String>();
		if(org.apache.commons.collections.CollectionUtils.isEmpty(lowerList))
			return null;
		for(String low : lowerList) {
			upperList.add(low.toUpperCase());
		}
		return upperList;
	}
	@Override
	public void bookCaseCheck(JSONObject data) throws BizException {
		JSONArray arr = data.getJSONArray("data");
		for(int i=0; i< arr.size(); i++) {
			JSONObject jsonObj = (JSONObject) arr.get(i);
			Set<String> keys = jsonObj.keySet();
			for(String key : keys) {
				List<String> rfidList = (List<String>) jsonObj.get(key);
				List<String> upperList = toUpperList(rfidList);
				if(null == upperList)
					continue;
				bookGridCheck(key, upperList);
//				for(String rfid : rfidList) {
//					try {
//					BookEntityDO result = bookEntityDAO.get(rfid.toUpperCase());
//					if(result.getCurrentGridCode() != null && key.equalsIgnoreCase(result.getCurrentGridCode())) {
//						if(0 == result.getBorrowedStatus()) {
//							continue;	
//						}else if(1 == result.getBorrowedStatus()) {	//1.表示下架
//							//FIXME
//						}else {	//2.表示借阅
//							//FIXME
//						}
//					}else {
//						result.setBorrowedStatus(0);
//						result.setCreateTime(new Date());
//						result.setCurrentGridCode(key);
//						result.setOriginGridCode(key);
//						result.setPutonDate(new Date());
//						result.setStatus(1);
//						bookEntityDAO.update(result);
//					}
//					}catch(Exception e) {
//						logger.error("书格编号[{}]中， rfid:{} NotFoundInBookEntity",key, rfid);
//					}
//				}
			}
		}
		//1.从数据库中查询数据
//		List<BookGridDO> bookgridCodes = bookGridDAO.getBookGridCodes(shelf_code);
//		Map<String, List<String>> map = new HashMap<String, List<String>>();
		
//		for(BookGridDO gridCode : bookgridCodes) {
//			List<String> db_rfidcodes = bookEntityDAO.getRfidcodes(gridCode.getBookgridCode());
//			map.put(gridCode.getBookgridCode(), db_rfidcodes);
//		}
//		Map<String, Object> db_map = new HashMap<String, Object>();
//		db_map.put("data", map);
//		db_map.put("bookshelf_code", shelf_code);
//		String db_data_json = JSON.toJSONString(db_map);
//		//2.创建目录
//		String os = System.getenv("OS");
//		String single_shelf_inventory_path = "";
//		if("Windows_NT".equalsIgnoreCase(os)) {
//			single_shelf_inventory_path = configInfoManager.getValue("single_shelf_inventory_path_windows");
//		}else {
//			single_shelf_inventory_path = configInfoManager.getValue("single_shelf_inventory_path");
//		}
//		DateFormat df = new SimpleDateFormat("yyyyMMdd");
//		String datePath = df.format(new Date());
//		String yearMonth = datePath.substring(0, 6);
//		String day = datePath.substring(6);
//		File dir = mkdir(single_shelf_inventory_path, yearMonth);
//		File shelfcode_file = new File(dir, day + "_" +shelf_code + ".txt");
//		if(!shelfcode_file.exists()) {
//			try {
//				shelfcode_file.createNewFile();
//			} catch (IOException e) {
//				e.printStackTrace();
//			}
//		}
//		//3.写入数据
//		String[] lines = new String[] {DateFormatUtil.formatDateTime(new Date()), data.toJSONString(), db_data_json, System.getProperty("line.separator")};
//		try {
//			IOUtils.appendLines(shelfcode_file, lines);
//		} catch (IOException e) {
//			logger.error("写入文件[" + shelfcode_file.getAbsolutePath() + "]异常", e);
//		}

	}

	
	@Override
	public void singleShelfInventory(SingleShelfInventoryDTO inventory)  throws BizException{
		JSONObject jsonObject = (JSONObject) JSON.parse(inventory.getStockdata());
		bookCaseCheck(jsonObject);
	}

	@Override
	public String bookGridStatusReport(String bookgridCode, String status) throws BizException {
		BookGridDO bookGridDO = bookGridDAO.get(bookgridCode);
		if(null == bookGridDO)
			return null;
		logger.info("数据库中书格[{}]目前的状态为[{}]", bookgridCode, bookGridDO.getLockStatus());
		//status =1 开;   =0 关
		if("1".equals(status)) {
			if(BizConstants.GRID_LOCK_STATUS_0.equals(bookGridDO.getLockStatus())) {	//请求打开
				BookGridTransDO query = new BookGridTransDO();
				query.setGridCode(bookgridCode);
				query.setLockStatus(BizConstants.GRID_LOCK_STATUS_0);
				BookGridTransDO bookGridTransDO = bookGridTransDAO.getByCondition(query);
				if(null != bookGridTransDO) {
					bookGridTransDO.setLockStatus(BizConstants.GRID_LOCK_STATUS_1);			//1表示开门成功
					bookGridTransDO.setCreateTime(DateUtil.now());
					bookGridTransDO.setModifyTime(DateUtil.now());
					bookGridTransDAO.update(bookGridTransDO);
					bookGridDO.setLockStatus(BizConstants.GRID_LOCK_STATUS_1);	
					bookGridDAO.update(bookGridDO);
					return "1_" + bookGridTransDO.getUserId();	//1 表示开柜成功
					//2.通知数据总线该书柜已打开 或失败
//					String action =  WsAPPEnum.unlock_success.name();
//					bookGridManager.notifyApp(bookGridTransDO.getUserId(), bookgridCode, action);
				}
			}else if(BizConstants.GRID_LOCK_STATUS_5.equals(bookGridDO.getLockStatus())) {	//已关闭
				//FIXME  目前使用java客户端测试时，直接将书格的状态从5变为1，而不是3变为1 待更新数据
				bookGridDO.setLockStatus(BizConstants.GRID_LOCK_STATUS_1);
				bookGridDAO.update(bookGridDO);
				BookGridTransDO bookGridTrans = new BookGridTransDO();
				bookGridTrans.setCreateTime(new Date());
				bookGridTrans.setGridCode(bookgridCode);
				bookGridTrans.setLockStatus(BizConstants.GRID_LOCK_STATUS_1);
				bookGridTrans.setModifyTime(new Date());
				bookGridTrans.setPresentDate(new Date());
				bookGridTrans.setUserId(Long.valueOf(configInfoManager.getValue("default_maintain_user_id")));
				bookGridTrans.setUserType(1);
				bookGridTransDAO.insert(bookGridTrans);
				return "0_" + bookGridTrans.getUserId(); //0表示运维人员进行开柜请求
			}
		}else if("0".equals(status)){	//关
			BookGridTransDO query = new BookGridTransDO();
			query.setGridCode(bookgridCode);
			query.setLockStatus(BizConstants.GRID_LOCK_STATUS_1);
			BookGridTransDO bookGridTransDO = bookGridTransDAO.getByCondition(query);
			if(BizConstants.GRID_LOCK_STATUS_5 == bookGridDO.getLockStatus() || null == bookGridTransDO) {
				BookGridTransDO bookGridTrans = new BookGridTransDO();
				bookGridTrans.setCreateTime(new Date());
				bookGridTrans.setGridCode(bookgridCode);
				bookGridTrans.setLockStatus(BizConstants.GRID_LOCK_STATUS_3);
				bookGridTrans.setModifyTime(new Date());
				bookGridTrans.setPresentDate(new Date());
				bookGridTrans.setUserId(Long.valueOf(configInfoManager.getValue("default_maintain_user_id")));
				bookGridTrans.setUserType(1);
				bookGridTransDAO.insert(bookGridTrans);
				bookGridDO.setLockStatus(BizConstants.GRID_LOCK_STATUS_3);
				bookGridDO.setModifyTime(new Date());
				bookGridDAO.update(bookGridDO);
				return "2_" + bookGridTrans.getUserId();	//2表示运维人员进行关柜
			}else {
				Long userid = bookGridTransDO.getUserId();
				bookGridTransDO.setLockStatus(BizConstants.GRID_LOCK_STATUS_3);
				bookGridTransDO.setModifyTime(new Date());
				bookGridTransDAO.update(bookGridTransDO);
				//同时需要更新书格中的状态
				bookGridDO.setLockStatus(BizConstants.GRID_LOCK_STATUS_3);
				bookGridDO.setModifyTime(new Date());
				bookGridDAO.update(bookGridDO);
				return "3_" + userid;// 3 表示APP用户进行关柜
//				//通知APP，关门完成
//				bookGridManager.notifyApp(userid, bookgridCode, WsAPPEnum.lock_success.name());
			}
		}
		return "-1_111";	//表示异常
	}
	
	@Override
	public void singleGridReport(SingleGridReportDTO report)  throws BizException{
		BookGridDO bookGridDO = bookGridDAO.get(report.getBookgrid_code());
		if(bookGridDO == null)
			return ;
		if(bookGridDO.getLockStatus() == BizConstants.GRID_LOCK_STATUS_1 && 0 ==report.getBookgrid_status()) {
			bookGridDO.setLockStatus(BizConstants.GRID_LOCK_STATUS_5);
			bookGridDAO.update(bookGridDO);
		}else if(bookGridDO.getLockStatus() == BizConstants.GRID_LOCK_STATUS_3 && 1 == report.getBookgrid_status()) {
			bookGridDO.setLockStatus(BizConstants.GRID_LOCK_STATUS_1);
			bookGridDAO.update(bookGridDO);
		}
	}

	@Override
	public void bookCaseStatusReport(Map<String, String> statuses) throws BizException {
		
		Set<Entry<String, String>> entrySet = statuses.entrySet();
		for(Entry<String, String> entry : entrySet) {
//			bookGridStatusReport(entry.getKey(), entry.getValue());
			logger.info("书柜汇报状态: 书格编号[{}], 书格状态[{}]", entry.getKey(), entry.getValue());
		}
	}

	
	@Override
	public void singleShelfReport(SingleShelfReportDTO report)  throws BizException{
		String statuses = report.getStatuses();
		JSONObject jsonObject = JSON.parseObject(statuses);
		Set<Entry<String, Object>> entrySet = jsonObject.entrySet();
		for(Entry e : entrySet) {
			String grid_code = (String) e.getKey();
			Integer grid_status = Integer.parseInt(e.getValue()+"");
			singleGridReport(new SingleGridReportDTO(grid_code, grid_status));	
		}
	}

	@Override
	public boolean isUnderOpening(Long userid, Integer userType) {
		
		BookGridTransDO query = new BookGridTransDO();
		query.setUserType(userType);
		query.setUserId(userid);
		query.setLockStatus(BizConstants.GRID_LOCK_STATUS_1);
		List<BookGridTransDO> list = bookGridTransDAO.getLockStatusByUser(query);
		return !CollectionUtils.isEmpty(list);
	}

	@Override
	public VenusSvcResp<Boolean> isBookShelfNormal(String gridCode)  throws BizException{
		
		VenusSvcResp<Boolean> resp = new VenusSvcResp<Boolean>();
		resp.setBody(true);
		String shelfCode = gridCode.substring(0, 10);
		BookShelfDO bookShelfDO = bookShelfDAO.get(shelfCode);
		if(null == bookShelfDO) {
			resp = new VenusSvcResp<Boolean>(RspCodeEnum.BOOKSHELF_IS_NOT_EXISTS);
			return resp ;
		}
		if(2 == bookShelfDO.getDamageReport()) {
			resp = new VenusSvcResp<Boolean>(RspCodeEnum.BOOKSHELF_IS_UNDER_DAMAGE);
			return resp ;
		}
		if(0 == bookShelfDO.getAvailable()) {
			resp = new VenusSvcResp<Boolean>(RspCodeEnum.BOOKSHELF_IS_UNAVAILABLE);
			return resp ;
		}
		return resp;
	}

	@Override
	public void singleGridTimeInventory(SingleGridInventoryDTO inventory)  throws BizException{
		//1.从数据库中查询的rfidcodes
		JSONObject jsonObject = (JSONObject) JSON.parse(inventory.getStockdata());
		String bookgrid_code = (String) jsonObject.get("bookgrid_code");
		List<String> db_rfidcodes = bookEntityDAO.getRfidcodes(bookgrid_code);
		
		singleGridLand(jsonObject, bookgrid_code, db_rfidcodes);
		
	}

	@Override
	public VenusSvcResp<Object> notifyInventory(Long userId)  throws BizException{
		
		VenusSvcResp<Object> resp = new VenusSvcResp<Object>();
		BookGridTransDO transDO = bookGridTransDAO.getLastestGridCodeByUser(userId);
		String gridCode = transDO.getGridCode();
		
		//1.判断书格状态是否为盘点成功状态
		BookGridDO bookGrid = bookGridDAO.get(gridCode);
		if(null == bookGrid) {
			resp.setRspCodeEnum(RspCodeEnum.BOOK_GRID_IS_NOT_EXISTS);
			return resp ;
		}
		if(5 != bookGrid.getLockStatus()) {
			resp.setRspCodeEnum(RspCodeEnum.BOOK_GRID_IS_UNDER_NON_INVENTORY);
			return resp ;
		}
		//2.书格最后一次开启是否是该人,根据书格编号查询最后一次操作的用户id
		BookGridTransDO lastTrans = bookGridTransDAO.getLastestUserByGridCode(gridCode);
		Long lastestUserId = lastTrans.getUserId();
		if(!userId.equals(lastestUserId)) {
			resp.setRspCodeEnum(RspCodeEnum.BOOK_GRID_FINALLY_USED_NON_OWN);
			return resp ;
		}
		//4.是否5分钟以内
		Long millSeconds = (new Date()).getTime() - transDO.getModifyTime().getTime() ;
		if(millSeconds > BizConstants.FIVE_MINUTES_MILLS) {
			resp.setRspCodeEnum(RspCodeEnum.BOOK_GRID_OVER_5_MINUTES);
			return resp ;
		}
		
		//5.修改书格、书格记录表状态
		bookGrid.setLockStatus(BizConstants.GRID_LOCK_STATUS_4);
		bookGrid.setModifyTime(new Date());
		bookGridDAO.update(bookGrid);
		transDO.setLockStatus(BizConstants.GRID_LOCK_STATUS_4);
		transDO.setModifyTime(new Date());
		bookGridTransDAO.update(transDO);
		//6.通知书柜进行盘点
		bookGridManager.notifyBookGrid(gridCode, null, WSBookShelfEnum.bookgrid_check_req);
		return resp;
	}

	@Override
	public BigDecimal getCostByUser(Long userid) throws BizException{
		List<BorrowingCostDO> list = orderTransDAO.getBorrowingCost(userid);
		if(ObjectUtils.isEmpty(list))
			return null;
		BigDecimal sum = new BigDecimal(0.00);
		for(BorrowingCostDO borrowingCost : list) {
			if(ObjectUtils.isEmpty(borrowingCost)) {
				continue;
			}
			BigDecimal price = borrowingCost.getBorrow_price();
			Date start = borrowingCost.getCreate_time();
			Date end = borrowingCost.getNow_time();
			Long millSeconds = (end.getTime() - start.getTime()) ;
			int minutes = (int)(millSeconds / 1000 / 60) ;
			if(minutes < 5) {
				continue ;
			}else if(minutes < 60 * 24){	//不足1天，则按照一天计算
				sum = sum.add(price);
			}else {
				int days = (int)( minutes / 60 / 24) ;
				int mod = minutes % (60*24);
				if(mod > 5) {
					days = days + 1 ;
				}
				sum = sum.add(new BigDecimal(days).multiply(price).setScale(2, RoundingMode.HALF_DOWN)) ;
			}
			
		}
		return sum;
	}

	@Override
	public PutonBook getPutonBookList(PutonBookPageDTO pageDTO) throws BizException{
		
		PutonBook putonBook = new PutonBook();
		
		//1.首先找出最后上架的书格的日期
		Date lastestDate = bookEntityDAO.getLastestPutonDate(pageDTO.getShelfCode());
		if(null == lastestDate)
			throw new BizException(RspCodeEnum.HAS_NOT_PUTON_BOOK);
		putonBook.setUpdatedate(DateFormatUtil.formatDate2(lastestDate));
		//2.根据最后上架的日期，查找条数
		PutonCountQueryDO query = new PutonCountQueryDO();
		query.setPutonDate(lastestDate);
		query.setShelfCode(pageDTO.getShelfCode());
		int putonCount = bookEntityDAO.getPutonCount(query);
		putonBook.setBookcount(putonCount);
		//3.分页查询书籍信息
		query.setOffset(pageDTO.getOffset());
		query.setPagesize(pageDTO.getPagesize());
		List<BorrowedBookDO> list = bookEntityDAO.getPutonList(query);
		if(CollectionUtils.isEmpty(list))
			throw new BizException(RspCodeEnum.QUERY_LIST_IS_NULL);
		
		for(BorrowedBookDO book : list) {
			BRBookDTO bookDTO = new BRBookDTO();
			bookDTO.setBookname(book.getBookname());
			bookDTO.setIsbn(book.getIsbn());
			bookDTO.setImgurl(configInfoManager.getImgurl(book.getImgurl())); 
			putonBook.getBooks().add(bookDTO);
		}
		return putonBook;
	}

	@Override
	public BookTagAgeDTO queryTagAgeList() throws BizException {
		
		BookTagAgeDTO bookTagAgeDTO = new BookTagAgeDTO();
		List<DictBookReadableDO> readableList = dictBookReadableDAO.list();
		
		List<BookTagMappingDO> mappingList = bookTagMappingDAO.list();
		
		if(!CollectionUtils.isEmpty(readableList)) {
			for(DictBookReadableDO readableDO : readableList) {
				Age age = new Age();
				age.setReadable(readableDO.getReadable());
				age.setAge(readableDO.getAge());
				bookTagAgeDTO.getAges().add(age);
			}
		}
		
		if(!CollectionUtils.isEmpty(mappingList)) {
			for(BookTagMappingDO mappingDO : mappingList) {
				BookTag bookTag = new BookTag();
				bookTag.setTag_code(mappingDO.getTagCode());
				bookTag.setTag_name(mappingDO.getTagName());
				bookTagAgeDTO.getTags().add(bookTag);
			}
		}
		
		return bookTagAgeDTO;
	}

	@Override
	public BookTopicalAgeDTO queryTopicalAgeList() throws BizException {
		
		BookTopicalAgeDTO bookTopicalAgeDTO = new BookTopicalAgeDTO();
		List<DictBookReadableDO> readableList = dictBookReadableDAO.list();
		if(!CollectionUtils.isEmpty(readableList)) {
			for(DictBookReadableDO readableDO : readableList) {
				Age age = new Age();
				age.setReadable(readableDO.getReadable());
				age.setAge(readableDO.getAge());
				bookTopicalAgeDTO.getAges().add(age);
			}
		}
		List<BookTopicalMappingsDO> mappingsList = bookTopicalMappingsDAO.list();
		if(!CollectionUtils.isEmpty(mappingsList)) {
			for(BookTopicalMappingsDO mappingDO : mappingsList) {
				BookTopical bookTopical = new BookTopical();
				bookTopical.setTopical_code(mappingDO.getTopicalCode());
				bookTopical.setTopical_name(mappingDO.getTopicalName());
				bookTopicalAgeDTO.getTopicals().add(bookTopical);
			}
		}
		return bookTopicalAgeDTO;
	}	
	
	@Override
	public BookQueryDTO queryBookList(BookQueryPageDTO bookQueryPageDTO) throws BizException{
		
		BookQueryDTO bookQuery = new BookQueryDTO();
		
		BookQueryPageDO bookQueryPageDO = new BookQueryPageDO();
		bookQueryPageDO.setOffset(bookQueryPageDTO.getOffset());
		bookQueryPageDO.setPagesize(bookQueryPageDTO.getPagesize());
		bookQueryPageDO.setTagCode(bookQueryPageDTO.getTag_code());
		bookQueryPageDO.setReadable(bookQueryPageDTO.getReadable());
		bookQueryPageDO.setShelfCode(bookQueryPageDTO.getShelf_code());
		
		int count = bookEntityDAO.countBookByCondition(bookQueryPageDO);
		List<BorrowedBookDO> bookList = bookEntityDAO.queryBookList(bookQueryPageDO);
		if(CollectionUtils.isEmpty(bookList))
			throw new BizException(RspCodeEnum.QUERY_LIST_IS_NULL);
		bookQuery.setTotalcount(count);
		for(BorrowedBookDO bookDO : bookList) {
			BRBookDTO brBookDTO = new BRBookDTO();
			brBookDTO.setBookname(bookDO.getBookname());
			brBookDTO.setIsbn(bookDO.getIsbn());
			brBookDTO.setImgurl(configInfoManager.getImgurl(bookDO.getImgurl()));
			bookQuery.getList().add(brBookDTO);
		}
		return bookQuery;
	}

	@Override
	public BookGridListDTO queryGridList(String shelfCode) throws BizException {
		
		List<BookGridDO> gridCodes = bookGridDAO.getBookGridCodes(shelfCode);
		if(CollectionUtils.isEmpty(gridCodes))
			throw new BizException(RspCodeEnum.QUERY_LIST_IS_NULL);
		BookGridListDTO listDTO = new BookGridListDTO();
		listDTO.setTotalcount(gridCodes.size());
		for(int i=0; i< gridCodes.size();i++) {
			BookGridDTO bookGrid = new BookGridDTO();
			bookGrid.setGrid_code(gridCodes.get(i).getBookgridCode());
			bookGrid.setGrid_name("书格" + (i+1));
			listDTO.getGrids().add(bookGrid);
		}
		return listDTO;
	}

	@Override
	public PutonBook queryGridBooks(BookGridPageDTO pageDTO) throws BizException {
		
		BookGridPageDO pageDO = new BookGridPageDO();
		pageDO.setGridCode(pageDTO.getGridCode());
		pageDO.setOffset(pageDTO.getOffset());
		pageDO.setPagesize(pageDTO.getPagesize());
		int bookCount = bookEntityDAO.countGridBooks(pageDO);
		if(0 == bookCount)
			throw new BizException(RspCodeEnum.QUERY_LIST_IS_NULL);
		List<BorrowedBookDO> list = bookEntityDAO.queryGridBooks(pageDO);
		if(CollectionUtils.isEmpty(list))
			throw new BizException(RspCodeEnum.QUERY_LIST_IS_NULL);
		
		PutonBook putonBook = new PutonBook();
		putonBook.setBookcount(bookCount);
		for(BorrowedBookDO bookDO : list) {
			BRBookDTO book = new BRBookDTO(bookDO.getIsbn(), bookDO.getBookname(), configInfoManager.getImgurl(bookDO.getImgurl()));
			putonBook.getBooks().add(book);
		}
		return putonBook;
	}

	@Override
	public BookShelfInfoDTO queryBookInfo(ShelfBookInfoDTO requestDTO) throws BizException {
		
		String isbn = requestDTO.getIsbn();
		BookShelfInfoDTO infoDTO = new BookShelfInfoDTO();
		
//		List<BookShelfInfoDO> shelfInfoDOList = bookInfoDAO.queryBookInfo(queryDO);
		BookInfoDO bookInfo = bookInfoDAO.get(isbn);
		if(null == bookInfo)
			throw new BizException(RspCodeEnum.OBJ_NOT_FOUND.setRspMessage("图书"));
		
		infoDTO.setAuthor(bookInfo.getAuthor());
		infoDTO.setBookname(bookInfo.getBookName());
		String describe = bookInfo.getDescribe();
		if(null != describe) {
			infoDTO.setDescribe(describe.replaceAll("\n", "<br/>").replaceAll("　", "&nbsp;").replaceAll(" ", "&nbsp;"));;
		}
		infoDTO.setImgurl(configInfoManager.getImgurl(bookInfo.getImgurl()));
		infoDTO.setPress(bookInfo.getPress());
		infoDTO.setIsbn(isbn);
		infoDTO.setPublish_date(DateFormatUtil.formatDate(bookInfo.getPublicationDate()));
		infoDTO.setStored(0);
		String shelfCode = requestDTO.getShelf_code();
		if(!ObjectUtils.isEmpty(shelfCode) && null != requestDTO.getUser_latitude() && null != requestDTO.getUser_longitude()) {
			BookShelfDO bookShelfDO = bookShelfDAO.get(shelfCode);
			infoDTO.setAddress(bookShelfDO.getArea());
			infoDTO.setShelf_code(shelfCode);
			//设置距离
			String distance = MapUtils.getDistance(bookShelfDO.getLatitude(), bookShelfDO.getLongitude(), requestDTO.getUser_latitude(), requestDTO.getUser_longitude());
			infoDTO.setDistance(distance);
			
		}
		
		BookContentAttachDO bookContentAttach = bookContentAttachDAO.getByIsbn(isbn);
		if(null != bookContentAttach) {
			infoDTO.setAuthor_desc(bookContentAttach.getAuthorDesc().replaceAll("\n", "<br/>").replaceAll("　", "&nbsp;").replaceAll(" ", "&nbsp;"));
			infoDTO.setAuthor_recommendation(bookContentAttach.getAuthorRecommendation().replaceAll("\n", "<br/>").replaceAll("　", "&nbsp;").replaceAll(" ", "&nbsp;"));
		}
		//设置banner图片
		BookImageAttachDO query = new BookImageAttachDO();
		query.setIsbn(isbn);
		query.setImageType(2);
		boolean flag = true;
		List<String> imgBanners = bookImageAttachDAO.getImgUrlList(query);
		if(!CollectionUtils.isEmpty(imgBanners)) {
			for(String imgBanner : imgBanners) {
				if(flag) {
					infoDTO.setImgurl(configInfoManager.getImgurl(imgBanner));
					flag = false;
				}
				BookUrlDTO bookUrl = new BookUrlDTO();
				bookUrl.setBookurl(configInfoManager.getImgurl(imgBanner));
				infoDTO.getBookbanners().add(bookUrl);
			}
		}else {
			BookUrlDTO bookUrl = new BookUrlDTO();
			bookUrl.setBookurl(configInfoManager.getImgurl(bookInfo.getImgurl()));
			infoDTO.getBookbanners().add(bookUrl);
		}
		
		//设置详情上图片
		BookImageAttachDO query2 = new BookImageAttachDO();
		query2.setIsbn(isbn);
		query2.setImageType(3);
		List<String> imgDetails = bookImageAttachDAO.getImgUrlList(query2);
		if(!CollectionUtils.isEmpty(imgDetails)) {
			for(String imgDetail : imgDetails) {
				BookUrlDTO bookUrl = new BookUrlDTO();
				bookUrl.setBookurl(configInfoManager.getImgurl(imgDetail));
				infoDTO.getBookurls().add(bookUrl);
			}
		}
		
		
		BookRecommendationDO bookRecommendationDO = bookRecommendationDAO.get(isbn);
		if(null == bookRecommendationDO)
			infoDTO.setRecommendation(0);
		else	
			infoDTO.setRecommendation(bookRecommendationDO.getRecommendation());
		
		//设置封面图片
//		List<String> bookImgs = bookImgsDAO.getUrls(isbn);
//		for(String img : bookImgs) {
//			BookUrlDTO bookUrl = new BookUrlDTO();
//			bookUrl.setBookurl(configInfoManager.getImgurl(img));
//			infoDTO.getBookurls().add(bookUrl);
//			infoDTO.getBookbanners().add(bookUrl);
//		}
		

		return infoDTO;
	}

	@Override
	public PutonBook getRankBookList(PutonBookPageDTO pageDTO) throws BizException {
		PutonBook putonBook = new PutonBook();
		PutonCountQueryDO query = new PutonCountQueryDO();
		query.setShelfCode(pageDTO.getShelfCode());
		query.setOffset(pageDTO.getOffset());
		query.setPagesize(pageDTO.getPagesize());
		int count = bookEntityDAO.countRankBookList(query);
		if(count == 0) {
			throw new BizException(RspCodeEnum.QUERY_LIST_IS_NULL);
		}
		putonBook.setBookcount(count);
		List<BorrowedBookDO> list = bookEntityDAO.getRankBookList(query);
		if(CollectionUtils.isEmpty(list))
			throw new BizException(RspCodeEnum.QUERY_LIST_IS_NULL);
		for(BorrowedBookDO book : list) {
			BRBookDTO bookDTO = new BRBookDTO();
			bookDTO.setBookname(book.getBookname());
			bookDTO.setIsbn(book.getIsbn());
			bookDTO.setImgurl(configInfoManager.getImgurl(book.getImgurl())); 
			putonBook.getBooks().add(bookDTO);
		}
		return putonBook;
	}

	@Override
	public List<BookRecommendationInfoDTO> queryBookBorrowCountAndRecommendation(BookQueryPageDTO query) throws BizException {
		
		BookQueryPageDO bookQueryPageDO = new BookQueryPageDO(); 
		bookQueryPageDO.setShelfCode(query.getShelf_code());
		bookQueryPageDO.setPagesize(query.getPagesize());
		bookQueryPageDO.setOffset(query.getOffset());
		List<BookRecommendationInfoDO> list = bookInfoDAO.queryBookBorrowCountAndRecommendation(bookQueryPageDO);
		if(CollectionUtils.isEmpty(list))
			return null;
		List<BookRecommendationInfoDTO> dtoList = new ArrayList<BookRecommendationInfoDTO>();
		for(BookRecommendationInfoDO infoDO : list) {
			BookRecommendationInfoDTO dto = new BookRecommendationInfoDTO();
			BeanUtils.copyProperties(infoDO, dto);
			dto.setImgurl(configInfoManager.getImgurl(infoDO.getImgurl()));
			dtoList.add(dto);
		}
		return dtoList;
	}

	@Override
	public ShelfBookQueryDTO queryShelfBookList(BookQueryPageDTO bookQueryPageDTO) throws BizException{
		
		
		BookQueryPageDO bookQueryPageDO = new BookQueryPageDO();
		bookQueryPageDO.setOffset(bookQueryPageDTO.getOffset());
		bookQueryPageDO.setPagesize(bookQueryPageDTO.getPagesize());
		bookQueryPageDO.setTagCode(bookQueryPageDTO.getTag_code());
		if(null != bookQueryPageDTO.getReadable() && !"".equals(bookQueryPageDTO.getReadable())) {
			String readable = bookQueryPageDTO.getReadable();
			DictBookReadableDO dbrDO = dictBookReadableDAO.getByReadable(readable);
			String age = dbrDO.getAge();
			int index = age.indexOf("-");
			bookQueryPageDO.setMinAge(Integer.valueOf(age.substring(0, index)));
			bookQueryPageDO.setMaxAge(Integer.valueOf(age.substring(index+1)));
		}
		bookQueryPageDO.setShelfCode(bookQueryPageDTO.getShelf_code());
		bookQueryPageDO.setTopicalCode(bookQueryPageDTO.getTopical_code());
		bookQueryPageDO.setSortBy(bookQueryPageDTO.getSort_by());
		bookQueryPageDO.setUserId(bookQueryPageDTO.getUserid());
		ShelfBookQueryDTO shelfBookQuerydto = new ShelfBookQueryDTO();
		
		int count = bookInfoDAO.countShelfBookList(bookQueryPageDO);
		shelfBookQuerydto.setTotalcount(count);
		
		List<BookRecommendationInfoDO> list = bookInfoDAO.queryShelfBookList(bookQueryPageDO);
		if(CollectionUtils.isEmpty(list))
			throw new BizException(RspCodeEnum.QUERY_LIST_IS_NULL);
		List<BookRecommendationInfoDTO> dtoList = new ArrayList<BookRecommendationInfoDTO>();
		for(BookRecommendationInfoDO infoDO : list) {
			BookRecommendationInfoDTO dto = new BookRecommendationInfoDTO();
			BeanUtils.copyProperties(infoDO, dto);
			if(dto.getFavorite() > 0) {
				dto.setFavorite(1);
			}
			dto.setImgurl(infoDO.getImgurl() != null ?configInfoManager.getImgurl(infoDO.getImgurl()) : null);
			dtoList.add(dto);
		}
		shelfBookQuerydto.setDtoList(dtoList);
		return shelfBookQuerydto;
	}

	@Override
	public BorrowedUserImgUrlDTO getBorrowedUserImgUrl(String isbn) throws BizException {
		
		BorrowedUserImgUrlDTO dto = new BorrowedUserImgUrlDTO();
		
		List<String> userImgList = orderTransDAO.getBorrowedUserImg(isbn);
		if(CollectionUtils.isEmpty(userImgList))
			throw new BizException(RspCodeEnum.QUERY_LIST_IS_NULL);
		
		List<String> urls = new ArrayList<String>();
		for(String userImg : userImgList) {
			String url = configInfoManager.getImgurl2(userImg);
			urls.add(url);
		}
		dto.setUrls(urls);
		int count = orderTransDAO.countBorrowedUserImg(isbn);
		dto.setTotalcount(count);
		return dto;
	}

	@Override
	public BookCommentsAndUserDTO queryComments(BookCommentsQueryPageDTO pageDTO) throws BizException {
		
		BookCommentsPageDO pageDO = new BookCommentsPageDO();
		
		pageDO.setIsbn(pageDTO.getIsbn());
		pageDO.setOffset(pageDTO.getOffset());
		pageDO.setPagesize(pageDTO.getPagesize());
		
		int count = bookCommentsDAO.countComments(pageDTO.getIsbn());
		List<BookCommentsAndUserDO> list = bookCommentsDAO.queryComments(pageDO);	
		
		BookCommentsAndUserDTO dto = new BookCommentsAndUserDTO();
		dto.setTotalcount(count);
		
		if(CollectionUtils.isEmpty(list))
			throw new BizException(RspCodeEnum.QUERY_LIST_IS_NULL);
		for(BookCommentsAndUserDO commentsDO : list) {
			BookCommentsAndUser comments = new BookCommentsAndUser();
			comments.setComments(commentsDO.getComments());
			comments.setUsername(commentsDO.getUsername());
			comments.setImgurl(configInfoManager.getImgurl2(commentsDO.getImgurl()));
			Date commentsTime = commentsDO.getCommentsTime();
			comments.setTimeago(getTimeAgo(commentsTime));
			comments.setId(commentsDO.getId());
			dto.getList().add(comments);
		}
		
		return dto;
	}
	
	private String getTimeAgo(Date commentsTime) {
		
		long nowTime = System.currentTimeMillis();	//获取当前时间的毫秒数  
		long reset=commentsTime.getTime();   //获取指定时间的毫秒数  
		String msg = null;
		long dateDiff=nowTime-reset;  
		logger.info("dataDiff================{}", dateDiff);
		if(dateDiff<0){  
            msg="刚刚";  
        }else{  
	        long dateTemp1=dateDiff/1000; //秒  
	        long dateTemp2=dateTemp1/60; //分钟  
	        long dateTemp3=dateTemp2/60; //小时  
	        long dateTemp4=dateTemp3/24; //天数  
	        long dateTemp5=dateTemp4/30; //月数  
	        long dateTemp6=dateTemp5/12; //年数  
	          
	        if(dateTemp6>0){  
	            msg = dateTemp6+"年前";  
	        }else if(dateTemp5>0){  
	            msg = dateTemp5+"个月前";  
	        }else if(dateTemp4>0){  
	            msg = dateTemp4+"天前";  
	        }else if(dateTemp3>0){  
	            msg = dateTemp3+"小时前";  
	        }else if(dateTemp2>0){  
	            msg = dateTemp2+"分钟前";  
	        }else{  
	            msg = "刚刚";  
	        }     
	    }  
        return msg;  
	}

	@Override
	public BookShelfFavoriteDTO queryMapShelfBook(String shelfCode, Long userId) throws BizException {
		
		int storedCount = bookEntityDAO.queryStoredCount(shelfCode);
		
		BookShelfFavoriteDTO favoriteDTO = new BookShelfFavoriteDTO();
		favoriteDTO.setStored_count(storedCount);
		
		WishInfoQueryDO queryDO = new WishInfoQueryDO();
		queryDO.setShelfCode(shelfCode);
		queryDO.setUserId(userId);
		int favoriateCount = userWishListDAO.countByShelfCodeAndUserId(queryDO);
		favoriteDTO.setFavorite_count(favoriateCount);
		return favoriteDTO;
	}

	@Override
	public void saveBookComments(BookCommentsInsertDTO bookComments) throws BizException {
		
		if(bookComments.getComments().length() > 500)
			throw new BizException(RspCodeEnum.BOOK_COMMENTS_OVER_500);
		
		BookCommentsDO bookCommentsDO = new BookCommentsDO();
		bookCommentsDO.setComments(bookComments.getComments());
		bookCommentsDO.setUserId(bookComments.getUserId());
		bookCommentsDO.setIsbn(bookComments.getIsbn());
		bookCommentsDO.setCreateTime(new Date());
		bookCommentsDAO.insert(bookCommentsDO);
		Long userid = bookComments.getUserId();
		if(null != userid && 0 != userid) {
			UserPointDO userPoint = userPointDAO.getByUserId(userid);
			if(null != userPoint) {
				UserPointLogDO query = new UserPointLogDO();
				query.setChangeType(45);
				query.setPointId(userPoint.getId());
				query.setCreateTime(new Date());
				int count = userPointLogDAO.countByCondition(query);
				if(count < 10) {
					UserPointLogDO userPointLog = new UserPointLogDO();
					userPointLog.setPointId(userPoint.getId());
					userPointLog.setChangeType(45);
					userPointLog.setChangeValue(3);
					userPointLog.setCreateTime(new Date());
					userPointLogDAO.save(userPointLog);
					userPoint.setPointValue(userPoint.getPointValue()+3);
					userPoint.setModifyTime(new Date());
					userPointDAO.update(userPoint);
				}
			}
		}
		
	}

	@Override
	public BookGridsDTO getGridList(BookGridListRequestModel requestModel) throws BizException {
		
		List<BookGridInfoDO> list = bookEntityDAO.getBookGrids(requestModel.getShelfCode());
		
		List<BookGridDO> grids = bookGridDAO.getBookGridCodes(requestModel.getShelfCode());
		
		BookGridsDTO dto = new BookGridsDTO();
		dto.setTotalcount(grids.size());
		List<BookGridInfo> infoList = new ArrayList<BookGridInfo>();
		Map<String, BookGridInfo> map = new HashMap<String, BookGridInfo>();
		BookShelfDO bookShelfDO = bookShelfDAO.get(requestModel.getShelfCode());
		Integer sortBy = bookShelfDO.getSortBy();
		if(0 == sortBy) {
			int middle = grids.size() / 2;
			for(int i=1; i <= middle; i++) {
				
				if(i < 10) {
					BookGridInfo bookGridInfo = new BookGridInfo(requestModel.getShelfCode() + ("0"+i), 0, 0); 
					BookGridDO bookGrid = grids.get(i-1);
					if(2 == bookGrid.getDamageReport() || 0 == bookGrid.getAvailable()) {
						bookGridInfo.setDamage_flag(1);
					}
					infoList.add(bookGridInfo);
				}
				if(middle<10) {
					BookGridInfo bookGridInfo = new BookGridInfo(requestModel.getShelfCode() + ("0"+(middle+i)), 0, 0);
					BookGridDO bookGrid = grids.get(middle+i -1);
					if(2 == bookGrid.getDamageReport() || 0 == bookGrid.getAvailable()) {
						bookGridInfo.setDamage_flag(1);
					}
					infoList.add(bookGridInfo);
					
				}
			}
		}else if(1 == sortBy) {
			for(int i=1; i<= grids.size();i++) {
				BookGridInfo bookGridInfo = new BookGridInfo(requestModel.getShelfCode() + ("0"+i), 0, 0);
				BookGridDO bookGrid = grids.get(i - 1);
				if(2 == bookGrid.getDamageReport() || 0 == bookGrid.getAvailable()) {
					bookGridInfo.setDamage_flag(1);
				}
				infoList.add(bookGridInfo);
			}
		}
		
		for(BookGridDO bookGridDO : grids) {
			for(BookGridInfo info : infoList) {
				if(info.getBookgrid_code().equals(bookGridDO.getBookgridCode())) {
					info.setBookgrid_img(configInfoManager.getImgurl(bookGridDO.getBookgridImg()));
					map.put(bookGridDO.getBookgridCode(), info);
				}
			}
		}
		
		if(CollectionUtils.isEmpty(list)) {
			dto.setList(infoList);
			return dto;
		}
		boolean isEmpty = ( null == requestModel.getIsbnList() || requestModel.getIsbnList().length == 0);
		
		List isbnList = isEmpty ? null : Arrays.asList(requestModel.getIsbnList());
	
		for(BookGridInfoDO infoDO : list) {
			BookGridInfo info = map.get(infoDO.getGridCode());
			info.setStored_count(info.getStored_count()+1);
			if(!isEmpty) {
				if(isbnList.contains(infoDO.getIsbn()) && !info.getIsbn_list().contains(infoDO.getIsbn())) {
					info.setFavorite_count(info.getFavorite_count()+1);
					info.getIsbn_list().add(infoDO.getIsbn());
				}
			}
		}
		dto.setList(infoList);
		return dto;
	}

	@Override
	public void bookGridStatusReportCron() throws BizException {
		
		//1.查询当前书格中正在打开的书格状态是否是0，并且距离创建时间大于65秒，则修改数据
		List<BookGridTransDO> openingList = bookGridTransDAO.getOpeningList();
		logger.info("bookGridStatusReportCron, openingList.size: {}", (openingList != null && !openingList.isEmpty() ? openingList.size() : 0));
		for(BookGridTransDO trans : openingList) {
			trans.setLockStatus(2);
			trans.setModifyTime(new Date());
			String gridCode = trans.getGridCode();
			logger.info("bookGridStatusReportCron====[{}]的书格状态为 请求打开，并且时间超过65秒", gridCode);
			BookGridDO bookGrid = bookGridDAO.get(gridCode);
			bookGridTransDAO.update(trans);
			bookGrid.setLockStatus(2);//如果超过65秒，书格还未打开，则修改为打开失败
			bookGridDAO.update(bookGrid);
		}
	}

	@Override
	public String unlockFailed(String gridCode) throws BizException {
		
		//1.更新书格记录流水
		BookGridTransDO query = new BookGridTransDO();
		query.setGridCode(gridCode);
		BookGridTransDO bookGridTransDO = bookGridTransDAO.getByCondition(query);
		bookGridTransDO.setLockStatus(BizConstants.GRID_LOCK_STATUS_2);
		bookGridTransDO.setModifyTime(new Date());
		bookGridTransDAO.update(bookGridTransDO);
		
		//2.更新书格状态
		BookGridDO bookGrid = new BookGridDO();
		bookGrid.setBookgridCode(gridCode);
		bookGrid.setLockStatus(BizConstants.GRID_LOCK_STATUS_2);
		bookGridDAO.update(bookGrid);
		return bookGridTransDO.getUserId()+"";
//		bookGridManager.notifyApp(bookGridTransDO.getUserId(), gridCode, WsAPPEnum.unlock_failed.name());
	}

	@Override
	public void unlockOvertime(Long userid) throws BizException {
		
		UserInfoDO userInfo = userInfoDAO.get(userid);
		String registrationId = userInfo.getRegistrationId();
		if(!ObjectUtils.isEmpty(registrationId)) {
			String ids[] = {registrationId};
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("push_type", "3");
			map.put("overtime_tip", configInfoManager.getValue("overtime_tip"));
			jPushManager.sendPushByRegistrationId(ids, map);
		}
		
	}

	@Override
	public ShareBookDTO shareBook(String isbn, Long userid) throws BizException {
		
		BookInfoDO bookInfo = bookInfoDAO.get(isbn);
		if(null == bookInfo) {
			throw new BizException(RspCodeEnum.OBJ_NOT_FOUND.setRspMessage("图书信息"));
		}
		
		if(null != userid && 0 != userid) {
			UserPointDO userPoint = userPointDAO.getByUserId(userid);
			if(null != userPoint) {
				UserPointLogDO query = new UserPointLogDO();
				query.setChangeType(43);
				query.setPointId(userPoint.getId());
				query.setCreateTime(new Date());
				int count = userPointLogDAO.countByCondition(query);
				if(count < 3) {
					UserPointLogDO userPointLog = new UserPointLogDO();
					userPointLog.setPointId(userPoint.getId());
					userPointLog.setChangeType(43);
					userPointLog.setChangeValue(5);
					userPointLog.setCreateTime(new Date());
					userPointLogDAO.save(userPointLog);
					userPoint.setPointValue(userPoint.getPointValue()+5);
					userPoint.setModifyTime(new Date());
					userPointDAO.update(userPoint);
				}
				
			}
		}
		ShareBookDTO dto = new ShareBookDTO();
		dto.setBookdesc(bookInfo.getDescribe());
		dto.setBookname(bookInfo.getBookName());
		dto.setImgurl(configInfoManager.getImgurl(bookInfo.getImgurl()));
		
		String shareurlPrefix = configInfoManager.getValue("share_book_url");
		String shareurl = shareurlPrefix+"=" + isbn;
		dto.setShareurl(shareurl);
		return dto;
	}

	@Override
	public void shelfIsOpened(String shelfCode) throws BizException {
		
		int count = bookGridDAO.countOpenedByShelfCode(shelfCode);
		if(0 != count) {
			throw new BizException(RspCodeEnum.BOOK_SHELF_IS_OPEN);
		}
	}

	@Override
	public String getGridCodeByIsbn(String shelfCode, String isbn) throws BizException {
		BookShelfAndIsbnDO shelfAndIsbn = new BookShelfAndIsbnDO();
		shelfAndIsbn.setIsbn(isbn);
		shelfAndIsbn.setShelfCode(shelfCode);
		String gridCode = bookEntityDAO.getGridCodeByIsbn(shelfAndIsbn);
		return gridCode;
	}

	@Override
	public String getOverQuotaTip(Long userId) throws BizException {
		
		//查询用户超额借书的数量
		int count = orderTransDAO.countOverQuotaByUserId(userId);
		if(0 == count) {
			return "";
		}
		//查询用户免费借书数量
		Integer costFlag = getCostFlag(userId);
		int freeCount = 0;
		if(0 == costFlag || 2 == costFlag) {
			freeCount = 3;
		}else {
			freeCount = 5;
		}
		
		//查询用户在借图书数量
		int borrowingCount = orderTransDAO.getBorrowingCount(userId);
		if(borrowingCount > freeCount) {
			String content = "您当前可借阅"+freeCount+"本书籍，已超额借阅"+count+"本，超额部分将按照每本(2元/天)费用收取!";
			return content;
		}
		return "";
		
	}

	@Override
	public boolean gridIsInShelf(String gridCode, String shelfCode) throws BizException {
		
		BookGridDO bookGrid = bookGridDAO.get(gridCode);
		if(null == bookGrid)
			return false;
		
		return bookGrid.getBookshelfCode().equals(shelfCode);
	}

	@Override
	public Integer isShowDrawTip(Long userId) throws BizException {
		//查看是否是当天第一次还书记录.
		
		String isAlert = configInfoManager.getValue("is_alert_for_lottery");
		if(!ObjectUtils.isEmpty(isAlert)) {
			Integer ia = Integer.valueOf(isAlert);
			if(ia == 0) {
				return 0;
			}
		}
		int returnCount = orderTransDAO.countCurrentDateReturnByUserId(userId);
		if(1 == returnCount) {
			int minite = orderTransDAO.getLastestLockMinites(userId);
			if(minite >= 5) {
				return 1;
			}
		}
		return 0;
	}

	@Override
	public Integer getCurrentDateReturnBookCount(Long userId) throws BizException {
		//查看是否有借阅还书记录.
		int returnCount = orderTransDAO.countCurrentDateReturnByUserId(userId);
		if(returnCount > 0) {
			return 1;
		}
		return 0;
	}
	
}
